﻿#include "pch.h"

namespace
{

    // 线程安全的随机数生成器
    class RandomGenerator
    {
    public:
        static RandomGenerator &instance()
        {
            static RandomGenerator gen;
            return gen;
        }

        uint64_t generate()
        {
            std::lock_guard<std::mutex> lock(mutex_);
            return engine_();
        }

    private:
        RandomGenerator()
        {
            // 使用硬件随机数初始化
            std::random_device rd;
            std::array<uint32_t, 4> seeds;
            for (auto &seed : seeds)
            {
                seed = rd();
            }
            std::seed_seq seq(seeds.begin(), seeds.end());
            engine_.seed(seq);
        }

        std::mutex mutex_;
        std::mt19937_64 engine_;
    };

    // 生成随机字节
    std::array<uint8_t, 16> generate_random_bytes()
    {
        std::array<uint8_t, 16> bytes;
        uint64_t rand1 = RandomGenerator::instance().generate();
        uint64_t rand2 = RandomGenerator::instance().generate();

        for (int i = 0; i < 8; ++i)
        {
            bytes[i] = static_cast<uint8_t>((rand1 >> (i * 8)) & 0xFF);
            bytes[i + 8] = static_cast<uint8_t>((rand2 >> (i * 8)) & 0xFF);
        }

        return bytes;
    }

    // 转换为UUID字符串格式
    std::string bytes_to_uuid_string(const std::array<uint8_t, 16> &bytes)
    {
        std::stringstream ss;
        ss << std::hex << std::nouppercase << std::setfill('0');

        // 时间低字段
        ss << std::setw(8) << ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
        ss << '-';
        // 时间中字段
        ss << std::setw(4) << ((bytes[4] << 8) | bytes[5]);
        ss << '-';
        // 时间高和版本字段（设置版本4）
        ss << std::setw(4) << (((bytes[6] & 0x0F) | 0x40) << 8 | (bytes[7] & 0xFF));
        ss << '-';
        // 变体和时钟序列（设置RFC 4122变体）
        ss << std::setw(4) << (((bytes[8] & 0x3F) | 0x80) << 8 | (bytes[9] & 0xFF));
        ss << '-';
        // 节点ID
        for (int i = 10; i < 16; ++i)
        {
            ss << std::setw(2) << static_cast<int>(bytes[i]);
        }

        return ss.str();
    }

    // 获取系统时间（100纳秒间隔，自1582年10月15日起）
    uint64_t get_system_time()
    {
        // UUID时间从1582年10月15日开始
        const auto epoch = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>(std::chrono::duration<int64_t, std::ratio<141427, 5>>(0));

        auto now = std::chrono::system_clock::now();
        auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now - epoch).count();

        // 转换为100纳秒间隔
        return static_cast<uint64_t>(nanos / 100);
    }

} // namespace

namespace uuid
{

    std::string generate_v4()
    {
        auto bytes = generate_random_bytes();

        // 设置版本为4（随机生成）
        bytes[6] = (bytes[6] & 0x0F) | 0x40;
        // 设置变体为RFC 4122
        bytes[8] = (bytes[8] & 0x3F) | 0x80;

        return bytes_to_uuid_string(bytes);
    }

    std::string generate_v1()
    {
        static std::atomic<uint64_t> clock_sequence(0);
        if (clock_sequence == 0)
        {
            clock_sequence = RandomGenerator::instance().generate() & 0x3FFF;
        }

        uint64_t time = get_system_time();
        uint64_t clock_seq = clock_sequence++;

        std::array<uint8_t, 16> bytes{};

        // 时间戳字段（低、中、高）
        bytes[0] = static_cast<uint8_t>((time >> 24) & 0xFF);
        bytes[1] = static_cast<uint8_t>((time >> 16) & 0xFF);
        bytes[2] = static_cast<uint8_t>((time >> 8) & 0xFF);
        bytes[3] = static_cast<uint8_t>(time & 0xFF);
        bytes[4] = static_cast<uint8_t>((time >> 40) & 0xFF);
        bytes[5] = static_cast<uint8_t>((time >> 32) & 0xFF);
        bytes[6] = static_cast<uint8_t>(((time >> 56) & 0x0F) | 0x10); // 版本1
        bytes[7] = static_cast<uint8_t>((time >> 48) & 0xFF);

        // 时钟序列
        bytes[8] = static_cast<uint8_t>(((clock_seq >> 8) & 0x3F) | 0x80); // 变体
        bytes[9] = static_cast<uint8_t>(clock_seq & 0xFF);

        // 节点ID（使用伪随机数代替真实MAC地址）
        auto random_bytes = generate_random_bytes();
        for (int i = 10; i < 16; ++i)
        {
            bytes[i] = random_bytes[i];
        }
        // 设置多播位（表示这不是真实MAC地址）
        bytes[10] |= 0x01;

        return bytes_to_uuid_string(bytes);
    }

} // namespace uuid